home *** CD-ROM | disk | FTP | other *** search
/ United Public Domain Gold 4 / United Public Domain Gold 4.iso / fredfish / ff.0065.dms / ff.0065.adf / Bawk / bawksym.c < prev    next >
C/C++ Source or Header  |  1987-04-04  |  9KB  |  434 lines

  1. /*
  2.  * Bawk C actions builtin functions, variable declaration, and
  3.  * stack management routines.
  4.  */
  5. #include <stdio.h>
  6. #include "bawk.h"
  7.  
  8. #define MAXARGS        10    /* max # of arguments to a builtin func */
  9. #define F_PRINTF    1
  10. #define F_GETLINE    2
  11. #define F_STRLEN    3
  12. #define F_STRCPY    4
  13. #define F_STRCMP    5
  14. #define F_TOUPPER    6
  15. #define F_TOLOWER    7
  16. #define F_MATCH        8
  17. #define F_NEXTFILE    9
  18.  
  19. isfunction( s )
  20. char *s;
  21. {
  22.     /*
  23.      * Compare the string "s" to a list of builtin functions
  24.      * and return its (non-zero) token number.
  25.      * Return zero if "s" is not a function.
  26.      */
  27.     if ( !strcmp( s, "printf" ) )
  28.         return F_PRINTF;
  29.     if ( !strcmp( s, "getline" ) )
  30.         return F_GETLINE;
  31.     if ( !strcmp( s, "strlen" ) )
  32.         return F_STRLEN;
  33.     if ( !strcmp( s, "strcpy" ) )
  34.         return F_STRCPY;
  35.     if ( !strcmp( s, "strcmp" ) )
  36.         return F_STRCMP;
  37.     if ( !strcmp( s, "toupper" ) )
  38.         return F_TOUPPER;
  39.     if ( !strcmp( s, "tolower" ) )
  40.         return F_TOLOWER;
  41.     if ( !strcmp( s, "match" ) )
  42.         return F_MATCH;
  43.     if ( !strcmp( s, "nextfile" ) )
  44.         return F_NEXTFILE;
  45.     return 0;
  46. }
  47.  
  48. iskeyword( s )
  49. char *s;
  50. {
  51.     /*
  52.      * Compare the string "s" to a list of keywords and return its
  53.      * (non-zero) token number.  Return zero if "s" is not a keyword.
  54.      */
  55.     if ( !strcmp( s, "char" ) )
  56.         return T_CHAR;
  57.     if ( !strcmp( s, "int" ) )
  58.         return T_INT;
  59.     if ( !strcmp( s, "if" ) )
  60.         return T_IF;
  61.     if ( !strcmp( s, "else" ) )
  62.         return T_ELSE;
  63.     if ( !strcmp( s, "while" ) )
  64.         return T_WHILE;
  65.     if ( !strcmp( s, "break" ) )
  66.         return T_BREAK;
  67.  
  68.     if ( !strcmp( s, "NF" ) )
  69.         return T_NF;
  70.     if ( !strcmp( s, "NR" ) )
  71.         return T_NR;
  72.     if ( !strcmp( s, "FS" ) )
  73.         return T_FS;
  74.     if ( !strcmp( s, "RS" ) )
  75.         return T_RS;
  76.     if ( !strcmp( s, "FILENAME" ) )
  77.         return T_FILENAME;
  78.     if ( !strcmp( s, "BEGIN" ) )
  79.         return T_BEGIN;
  80.     if ( !strcmp( s, "END" ) )
  81.         return T_END;
  82.     return 0;
  83. }
  84.  
  85. function( funcnum )
  86. {
  87.     int argc, args[ MAXARGS ];
  88.     char lpar;
  89.  
  90.     argc = 0;
  91.     if ( Token==T_LPAREN )
  92.     {
  93.         lpar = 1;
  94.         getoken();
  95.     }
  96.     else
  97.         lpar = 0;
  98.     /*
  99.      * If there are any arguments, evaluate them and copy their values
  100.      * to a local array.
  101.      */
  102.     if ( Token!=T_RPAREN && Token!=T_EOF )
  103.     {
  104.         for ( ;; )
  105.         {
  106.             expression();
  107.             if ( argc<MAXARGS )
  108.                 args[ argc++ ] = popint();
  109.             else
  110.                 popint();
  111.             if ( Token==T_COMMA )
  112.                 getoken();
  113.             else
  114.                 break;
  115.         }
  116.     }
  117.     if ( lpar && Token!=T_RPAREN )
  118.         error( "missing ')'", ACT_ERROR );
  119.     else if ( Token==T_RPAREN )
  120.         getoken();
  121.  
  122.     switch ( funcnum )
  123.     {
  124.     case F_PRINTF:    /* just like the real printf() function */
  125.         pushint( printf( args[0], args[1], args[2], args[3], args[4],
  126.              args[5], args[6], args[7], args[8], args[9] ) );
  127.         break;
  128.     case F_GETLINE:
  129.         /*
  130.          * Get the next line of input from the current input file
  131.          * and parse according to the current field seperator.
  132.          * Don't forget to free up the previous line's words first...
  133.          */
  134.         while ( Fieldcount )
  135.             free( Fields[ --Fieldcount ] );
  136.         pushint( getline() );
  137.         Fieldcount = parse( Linebuf, Fields, Fieldsep );
  138.         break;
  139.     case F_STRLEN:    /* calculate length of string argument */
  140.         pushint( strlen( args[0] ) );
  141.         break;
  142.     case F_STRCPY:    /* copy second string argument to first string */
  143.         pushint( strcpy( args[0], args[1] ) );
  144.         break;
  145.     case F_STRCMP:    /* compare two strings */
  146.         pushint( strcmp( args[0], args[1] ) );
  147.         break;
  148.     case F_TOUPPER:    /* convert the character argument to upper case */
  149.         pushint( toupper( args[0] ) );
  150.         break;
  151.     case F_TOLOWER:    /* convert the character argument to lower case */
  152.         pushint( tolower( args[0] ) );
  153.         break;
  154.     case F_MATCH:    /* match a string argument to a regular expression */
  155.         pushint( match( args[0], args[1] ) );
  156.         break;
  157.     case F_NEXTFILE:/* close current input file and process next file */
  158.         pushint( endfile() );
  159.         break;
  160.     default:    /* oops! */
  161.         error( "bad function call", ACT_ERROR );
  162.     }
  163. }
  164.  
  165. VARIABLE *
  166. findvar( s )
  167. char *s;
  168. {
  169.     /*
  170.      * Search the symbol table for a variable whose name is "s".
  171.      */
  172.     VARIABLE *pvar;
  173.     int i;
  174.     char name[ MAXVARLEN ];
  175.  
  176.     i = 0;
  177.     while ( i < MAXVARLEN && alphanum( *s ) )
  178.         name[i++] = *s++;
  179.     if ( i<MAXVARLEN )
  180.         name[i] = 0;
  181.  
  182.     for ( pvar = Vartab; pvar<Nextvar; ++pvar )
  183.     {
  184.         if ( !strncmp( pvar->vname, name, MAXVARLEN ) )
  185.             return pvar;
  186.     }
  187.     return NULL;
  188. }
  189.  
  190. VARIABLE *
  191. addvar( name )
  192. char *name;
  193. {
  194.     /*
  195.      * Add a new variable to symbol table and assign it default
  196.      * attributes (int name;)
  197.      */
  198.     int i;
  199.  
  200.     if ( Nextvar <= Vartab + MAXVARTABSZ )
  201.     {
  202.         i = 0;
  203.         while ( i<MAXVARLEN && alphanum( *name ) )
  204.             Nextvar->vname[i++] = *name++;
  205.         if ( i<MAXVARLEN )
  206.             Nextvar->vname[i] = 0;
  207.  
  208.         Nextvar->vclass = 0;
  209.         Nextvar->vsize = WORD;
  210.         Nextvar->vlen = 0;
  211.         /*
  212.          * Allocate some new room
  213.          */
  214.         Nextvar->vptr = getmem( WORD );
  215.         fillmem( Nextvar->vptr, WORD, 0 );
  216.     }
  217.     else
  218.         error( "symbol table overflow", MEM_ERROR );
  219.  
  220.     return Nextvar++;
  221. }
  222.  
  223. declist()
  224. {
  225.     /*
  226.      * Parse a "char" or "int" statement.
  227.      */
  228.     char type;
  229.  
  230.     type = Token;
  231.     getoken();
  232.     decl( type );
  233.     while ( Token==T_COMMA )
  234.     {
  235.         getoken();
  236.         decl( type );
  237.     }
  238.     if ( Token==T_SEMICOLON )
  239.         getoken();
  240. }
  241.  
  242. VARIABLE *
  243. decl( type )
  244. {
  245.     /*
  246.      * Parse an element of a "char" or "int" declaration list.
  247.      * The function stmt_compile() has already entered the variable
  248.      * into the symbol table as an integer, this routine simply changes
  249.      * the symbol's class, size or length according to the declaraction.
  250.      * WARNING: The interpreter depends on the fact that pointers are
  251.      * the same length as int's.  If your machine uses long's for
  252.      * pointers either change the code or #define int long (or whatever).
  253.      */
  254.     char class, size;
  255.     int len;
  256.     unsigned oldsize, newsize;
  257.     VARIABLE *pvar;
  258.  
  259.     if ( Token==T_MUL )
  260.     {
  261.         /*
  262.          * it's a pointer
  263.          */
  264.         getoken();
  265.         pvar = decl( type );
  266.         ++pvar->vclass;
  267.     }
  268.     else if ( Token==T_VARIABLE )
  269.     {
  270.         /*
  271.          * Simple variable so far.  The token value (in the global
  272.          * "Value" variable) is a pointer to the variable's symbol
  273.          * table entry.
  274.          */
  275.         pvar = Value.dptr;
  276.         getoken();
  277.         class = 0;
  278.         /*
  279.          * Compute its length
  280.          */
  281.         if ( Token==T_LBRACKET )
  282.         {
  283.             /*
  284.              * It's an array.
  285.              */
  286.             getoken();
  287.             ++class;
  288.             /*
  289.              * Compute the dimension
  290.              */
  291.             expression();
  292.             if ( Token!=T_RBRACKET )
  293.                 error( "missing ']'", ACT_ERROR );
  294.             getoken();
  295.             len = popint();
  296.         }
  297.         else
  298.             /*
  299.              * It's a simple variable - array length is zero.
  300.              */
  301.             len = 0;
  302.  
  303.         size = (type==T_CHAR) ? BYTE : WORD;
  304.  
  305.         newsize = (len ? len : 1) * size;
  306.         oldsize = (pvar->vlen ? pvar->vlen : 1) * pvar->vsize;
  307.         if ( newsize != oldsize )
  308.         {
  309.             /*
  310.              * The amount of storage needed for the variable
  311.              * has changed - free up memory allocated initially
  312.              * and reallocate for new size.
  313.              */
  314.             free( pvar->vptr );
  315.             pvar->vptr = getmem( newsize );
  316.         }
  317.         /*
  318.          * Now change the variable's attributes.
  319.          */
  320.         pvar->vclass = class;
  321.         pvar->vsize = size;
  322.         pvar->vlen = len;
  323.     }
  324.     else
  325.         syntaxerror();
  326.  
  327.     return pvar;
  328. }
  329.  
  330. assignment()
  331. {
  332.     /*
  333.      * Perform an assignment
  334.      */
  335.     int ival;
  336.  
  337.     ival = popint();
  338.     /*
  339.      * make sure we've got an lvalue
  340.      */
  341.     if ( Stackptr->lvalue )
  342.     {
  343.         if ( Stackptr->class )
  344.             movemem( &ival, Stackptr->value.dptr, WORD );
  345.         else
  346.             movemem(&ival, Stackptr->value.dptr, Stackptr->size);
  347.         pop();
  348.         pushint( ival );
  349.     }
  350.     else
  351.         error( "'=' needs an lvalue", ACT_ERROR );
  352. }
  353.  
  354. pop()
  355. {
  356.     /*
  357.      * Pop the stack and return the integer value
  358.      */
  359.     if ( Stackptr >= Stackbtm )
  360.         return (Stackptr--)->value.ival;
  361.     return error( "stack underflow", ACT_ERROR );
  362. }
  363.  
  364. push( pclass, plvalue, psize, pdatum )
  365. char pclass, plvalue, psize;
  366. DATUM *pdatum;
  367. {
  368.     /*
  369.      * Push item parts onto the stack
  370.      */
  371.     if ( ++Stackptr <= Stacktop )
  372.     {
  373.         Stackptr->lvalue = plvalue;
  374.         Stackptr->size = psize;
  375.         if ( !(Stackptr->class = pclass)  &&  !plvalue )
  376.             Stackptr->value.ival = pdatum->ival;
  377.         else
  378.             Stackptr->value.dptr = pdatum->dptr;
  379.     }
  380.     else
  381.         error( "stack overflow", MEM_ERROR );
  382. }
  383.  
  384. pushint( intvalue )
  385. int intvalue;
  386. {
  387.     /*
  388.      * push an integer onto the stack
  389.      */
  390.     if ( ++Stackptr <= Stacktop )
  391.     {
  392.         Stackptr->lvalue =
  393.         Stackptr->class = 0;
  394.         Stackptr->size = WORD;
  395.         Stackptr->value.ival = intvalue;
  396.     }
  397.     else
  398.         error( "stack overflow", MEM_ERROR );
  399. }
  400.  
  401. popint()
  402. {
  403.     /*
  404.      * Resolve the item on the top of the stack and return it
  405.      */
  406.     int intvalue;
  407.  
  408.     if ( Stackptr->lvalue )
  409.     {
  410.         /*
  411.          * if it's a byte indirect, sign extend it
  412.          */
  413.         if ( Stackptr->size == BYTE && !Stackptr->class )
  414.             intvalue = *Stackptr->value.dptr;
  415.         else
  416.         {
  417.             /*
  418.              * otherwise, it's an unsigned int
  419.              */
  420.             intvalue = *Stackptr->value.ptrptr;
  421.         }
  422.         pop();
  423.         return intvalue;
  424.     }
  425.     else
  426.     {
  427.         /*
  428.          * else it's an ACTUAL, just pop it
  429.          */
  430.         return pop();
  431.     }
  432. }
  433.  
  434.